/*##############################################################################
 * 文件：SqliteDB.h
 * 描述：sqlite3数据库操作简易封装
 * 作者：hickman
 * 时间：2016年12月15日
 * 版权：Copyright(C) 2016 Fsmeeting.com. All rights reserved.
 #############################################################################*/

#ifndef _20266D69_1291_4C2A_8708_56BE03DB0B74
#define _20266D69_1291_4C2A_8708_56BE03DB0B74

#include "depends/incfile.h"
#include "../../sqlite3xx/sqlite3xx.h"
#include "xCores.h"


namespace x2lib
{
	/*==============================================================================
	 * 描述：数据库操作简易封装类
	 =============================================================================*/
	class SqliteDB
	{
	public:
		SqliteDB();
		virtual ~SqliteDB(void);

		/*------------------------------------------------------------------------------
			* 描  述：初始化数据库
			* 参  数：[in] pszFile 数据库文件名，全路径，若为nullptr则创建内存数据库
			* 返回值：TRUE/FALSE 是否执行成功
			*----------------------------------------------------------------------------*/
		bool Init(const char* pszFile, const char* pszPwd = nullptr);

		/*------------------------------------------------------------------------------
			* 描  述：反初始化数据库
			* 参  数：
			* 返回值：无
			*----------------------------------------------------------------------------*/
		void UnInit();

		/*------------------------------------------------------------------------------
			* 描  述：获取数据库文件
			* 参  数：
			* 返回值：返回nullptr表示为内存数据库
			*----------------------------------------------------------------------------*/
		const char* GetFile();

		/*------------------------------------------------------------------------------
			* 描  述：删除数据库表
			* 参  数：[in] szTableName 数据库表名
			* 返回值：TRUE/FALSE 是否执行成功
			*----------------------------------------------------------------------------*/
		bool DropTable(const char* pszTable);

		/*------------------------------------------------------------------------------
			* 描  述：清空数据库表
			* 参  数：[in] szTableName 数据库表名
			* 返回值：TRUE/FALSE 是否执行成功
			*----------------------------------------------------------------------------*/
		bool CleanTable(const char* pszTable);

		bool UpgradeTable(const char* pszTable, const char* pszCreateSql);

		/*------------------------------------------------------------------------------
			* 描  述：判断数据库表是否存在
			* 参  数：[in] szTableName 数据库表名
			* 返回值：TRUE/FALSE 是否执行成功
			*----------------------------------------------------------------------------*/
		bool IsTableExist(const char* szTable);

		/*------------------------------------------------------------------------------
			* 描  述：判断数据库表指定字段是否存在
			* 参  数：[in] szTableName 数据库表名
			* 参  数：[in] szFiledName 数据库表字段名
			* 返回值：TRUE/FALSE 是否执行成功
			*----------------------------------------------------------------------------*/
		bool IsFiledExist(const char* pszTable, char* pszFiled);

		/*------------------------------------------------------------------------------
			* 描  述：增加数据库表字段
			* 参  数：[in] szTableName 数据库表名
			* 参  数：[in] szFiledName 数据库表字段名
			* 参  数：[in] szKeyType 数据库表字段类型
			* 返回值：TRUE/FALSE 是否执行成功
			*----------------------------------------------------------------------------*/
		bool AppendFiled(const char* pszTable, const char* pszFiled, const char* pszKeyType);

		/*------------------------------------------------------------------------------
			* 描  述：执行一条sql语句
			* 参  数：[in] szSql 语句
			* 返回值：TRUE/FALSE 是否执行成功
			*----------------------------------------------------------------------------*/
		bool ExecuteSql(const char* pszSql, int(*callback)(void*, int, char**, char**) = nullptr, void* p = nullptr);

		bool ExecuteSql(int(*callback)(void*, int, char**, char**), const char* pszSqlFmt, ...);

		bool BeginTransaction();
		bool RollbackTransaction();
		bool CommitTransaction();

		/*------------------------------------------------------------------------------
			* 描  述：插入一条数据
			* 参  数：[in] pszTable 目标表名
			* 参  数：[in] ... 键值对序列，【键名】格式必须为“I:aaa”“F:bbb”“S:ccc”，
			**					其中IFS固定，分别代表字段数据类型，aaa,bbb,ccc为任意字段名；
			**					【键值】紧跟键名；最后一个参数必须为nullptr，即可变参为奇数个
			**				如：InsertItem("UserInfo", "S:userName","小王", "I:age",18, nullptr)
			* 返回值：TRUE/FALSE 是否执行成功
			*----------------------------------------------------------------------------*/
		bool InsertItem(const char *pszTable, ...);
        bool insertItem(const char *pszTable, va_list va);

        //准备废弃，推荐使用ExecuteSql(szCreateSql)创建
		//bool CreateTable(const char* pszTable, ...);

        // callback可以为nullptr
        // coMethod = true 表示或， false表示与
        int SelectItems(const char* pszTable, bool coMethod, int(*callback)(void* pVoid, int nCount, char** pValue, char** pName), ...);
        int selectItems(const char* pszTable, bool coMethod, int(*callback)(void* pVoid, int nCount, char** pValue, char** pName), va_list va);
        int SelectItems(const char* pszTable, int(*callback)(void* pVoid, int nCount, char** pValue, char** pName) = nullptr, void* pVoid = nullptr, const char* pszCondition = nullptr);

		static bool Convert2(sqlite3xx::sqlite3db* pMemDB, const char* pszFile, bool toFile);

	private:
		char			m_szFile[1024];		// 数据库文件名称( 路径)
        sqlite3xx::sqlite3db *		m_pDB;
		//xCores::Mutex	m_mutex; // sqlite3.1以后支持线程安全
	};
}

#endif
